/*

  正方教务管理系统处理件

 接入正方系统的模块

*/

class h_zf {

	/**
	 *
	 * [public] 检查系统登录状态
	 *
	 * @param [object] user 用户对象
	 *
	 * @return [number] 1
	 *
	 */

	async checkZfLogin(user) {
		if(this._checkZfLogin(user))
			return true
		else
			return this.reject('-3007', 'zf user not logined in')
	 }

	 async checkCasLogin(user) {
	 	return this._checkCasLogin(user)
	 }

	/**
	 *
	 * [public] 登录系统
	 *
	 * @param [number] userType 用户类型 0 1 2 3
	 * @param [string] userId 用户ID
	 * @param [string] userPwd 用户密码
	 * @param [string] userVCode 用户验证码
	 * @param [object] user 用户对象
	 *
	 * @return [number] 1
	 *
	 */

	async zfLogin(userType = 0, userId, userPwd, user, captchaErrCount = 0) {
		if(this._checkZfLogin(user, userId))
			return user
		if(isNaN(userType) || userType < 0 || userType > 3)
			return this.reject('-3005', 'zf user type invalid')
		if(!userId || !userPwd)
			return this.reject('-3006', 'login data imperfact')
		const {zfSession, captcha} = await this._zfCaptchaRecognition()
		console.log('captcha recognition result:', captcha)
		let cookie = {}
		cookie[this.config.zf.url] = {
			'ASP.NET_SessionId': zfSession
		}
		const result = await this.common.reqPost({
			url: `${this.config.zf.url}default2.aspx`,
			cookie,
			headers: {
				'content-type': 'application/x-www-form-urlencoded',
				charset: 'UTF-8',
				Referer: 'http://jwc.gdcxxy.net/default2.aspx'
			},
			data: {
				__VIEWSTATE: this.config.zf.viewState.login,
				TextBox1: userId,
				TextBox2: userPwd,
				RadioButtonList1: ['学生', '教师', '部门', '访客'][userType],
				Button1: '',
				TextBox3: captcha
			},
			getStatus: true
		})
		console.log(result)
		const {status, data} = result
		if(status.code != 200) {
			await this._zfLogout(user)
			return this.reject('-3003', 'zf resources not found')
		}
		if(/alert\('验证码不正确！！'\)/.test(data)) {
			//重试十次还是不正确返回错误
			if(captchaErrCount >= 10)
				return this.reject('-3000', 'zf validate code invalid')
			captchaErrCount++
			console.error('retry validate captcha count:', captchaErrCount)
			return await this.zfLogin(userType, userId, userPwd, user, captchaErrCount)
		}
		if(/alert\('密码错误，如忘记密码，请与教务处联系!'\)/.test(data))
			return this.reject('-3001', 'zf password invalid')
		if(/alert\('用户名不存在或未按照要求参加教学活动！！'\)/.test(data))
			return this.reject('-3002', 'zf user not found or job in the rough')
		const $ = this.common.parseHTML(data)
		const zfData = {
			userId,
			userType,
			logined: true,
			session: zfSession,
			time: parseInt(Date.now() / 1000)
		}
		user.data.zf = zfData
		console.log(zfData)
		if(!user.session)
			return user
		await this.common.updateSessionData(user.session, {
			zf: zfData
		})
		return user
	}

	async zfLogout(user) {
		return await this._zfLogout(user)
	}

	async casLogin(userId, userPwd, user, userHashPwd) {
		if(this._checkCasLogin(user, userId, userHashPwd)) {
			return user
		}
		const {userLT, userExec} = await this._setCasSession(user)
	 	if(!user.data.cas || !user.data.cas.session)
	 		return this.reject('-3016', 'cas session not found')
	 	if(!userId || !userPwd || !userLT || !userExec)
			return this.reject('-3018', 'cas login data imperfact')
		const casSession = user.data.cas.session
		let cookie = {}
		cookie[this.config.cas.url] = {
			'JSESSIONID': casSession
		}
		const result = await this.common.reqPost({
			url: `${this.config.cas.url}login`,
			cookie,
			headers: {
				'content-type': 'application/x-www-form-urlencoded',
				charset: 'UTF-8',
				Referer: 'https://cas.gdcxxy.net/login?service=http://120.86.68.211:8080/Login'
			},
			getData: {
				service: 'http://120.86.68.211:8080/Login'
			},
			data: {
				username: userId,
				password: userPwd,
				lt: userLT,
				execution: userExec,
				_eventId: 'submit'
			},
			ignoreAuth: true,
			getStatus: true,
			getCookie: true
		})
		const {status, data} = result
		console.log(status, data, result.cookie)
		if(/<span id=\"status\" class=\"error_m\">您提供的凭证有误。<\/span>/.test(data))
			return this.reject('-3021', 'cas user login failed')
		if(/您多次输入密码错误，请休息一下/.test(data))
			return this.reject('-3035', 'cas user login fail count too many')
		if(status.code != 200 || !result.cookie[1] || !result.cookie[1]['CASTGC']) {
			await this._casLogout(user)
			return this.reject('-3019', 'cas login failed')
		}
		const casTgc = result.cookie[1]['CASTGC']
		user.data.cas = {
			userId,
			logined: true,
			tgc: casTgc,
			session: casSession,
			time: parseInt(Date.now() / 1000)
		}
		if(!user.session)
			return user
		await this.common.updateSessionData(user.session, {
			cas: user.data.cas
		})
		return 1
	}

	async updateCasPwd(userHashPwd, user) {
		if(!this._checkCasLogin(user))
			return this.reject('-3007', 'zf user not logined in')
		user.data.cas.userHashPwd = userHashPwd
		await this.common.updateSessionData(user.session, {
			cas: user.data.cas
		})
		return 1
	}

	async activeCasZfSession(userType = 0, userZfAuthId = '', user) {
		const {userId, tgc, session} = user.data.cas
		if(this._checkZfLogin(user, userId))
			return user
		let cookie = {}
		cookie[this.config.cas.url] = {
			'CASTGC': tgc,
			'JSESSIONID': session
		}
		console.log(cookie)
		let verifyCode
		console.log(userZfAuthId)
		if(!this._checkZfAuthId(userZfAuthId)) {
			const loginResult = await this.common.reqGet({
				url: `${this.config.zf.url}login_cas.aspx`,
				cookie,
				ignoreAuth: true,
				getStatus: true
			})
			console.log(loginResult.data)
			if(loginResult.status.code != 200) {
				await this._casLogout(user)
				return this.reject('-3020', 'cas active zf auth failed')
			}
			const temp = loginResult.data.match(/k=([A-Z0-9]{32})/)
			if(!temp || temp.length == 0) {
				await this._casLogout(user)
				return this.reject('-3020', 'cas active zf auth failed')
			}
			if(!temp[1]) {
				await this._casLogout(user)
				return this.reject('-3020', 'cas active zf auth failed')
			}
			verifyCode = temp[1]
			await this.hd.user.updateUserZfAuthId(userType, user.userId, verifyCode)
			console.error('user zf auth id is changed')
		}
		else {
			console.log('user zf auth id already exists')
			verifyCode = userZfAuthId
		}
		console.log(`user zf auth id is ${verifyCode}`)
		const verifyResult = await this.common.reqPost({
			url: `${this.config.zf.url}cas_verify.aspx`,
			headers: {
				'content-type': 'application/x-www-form-urlencoded',
				charset: 'UTF-8'
			},
			cookie,
			getData: {
				i: userId,
				k: verifyCode
			},
			data: {
				__VIEWSTATE: this.config.zf.viewState.casVerify
			},
			getStatus: true,
			getCookie: true
		})
		const {status, data} = verifyResult
		console.log(status)
		if(status.code == 405) {
			console.error('user zf auth id is expired')
			await this._casLogout(user)
			await this.hd.user.clearUserZfAuthId(userType, user.userId)
			return this.reject('-3053', 'zf auth id expired')
		}
		const matchResult = data.match(/<script language='javascript'>window.open\('.+_main.aspx\?xh=(.+)',/)
		console.log(matchResult, verifyResult.cookie, verifyResult.data)
		if(status.code != 200 || !matchResult || !matchResult[1] || !verifyResult.cookie[0] || !verifyResult.cookie[0]['ASP.NET_SessionId']) {
			await this._casLogout(user)
			return this.reject('-3020', 'cas active zf auth failed')
		}
		const zfSession = verifyResult.cookie[0]['ASP.NET_SessionId']
		const $ = this.common.parseHTML(data)
		user.data.zf = {
			userId,
			userType,
			logined: true,
			session: zfSession,
			verifyCode,
			time: parseInt(Date.now() / 1000)
		}
		if(!user.session)
			return user
		await this.common.updateSessionData(user.session, {
			zf: user.data.zf
		})
		return user
	}

	 /**
	  *
	  * [public] 获取用户信息
	  *
	  * @param 
	  *
	  */

	async getUserInfo(user) {
		if(!user.data.zf)
			return this.reject('-3009', 'zf user data not found')
		const {userType} = user.data.zf
		let userInfo
		switch(userType) {
			case 0:
				userInfo = await this._getStuInfo(user)
				return userInfo
			break
			case 1:
				userInfo = await this._getTchInfo(user)
				return userInfo
			break
			default:
				return this.reject('-3005', 'zf user type invalid')
		}
	}

	async getGrabCourse(user) {
		if(!this._checkZfLogin(user))
			return this.reject('-3007', 'zf user not logined in')
		const {userId, session} = user.data.zf
		let cookie = {}
	 	cookie[this.config.zf.url] = {
			'ASP.NET_SessionId': session
		}
		const result = await this.common.reqGet({
			url: `${this.config.zf.url}xf_xsqxxxk.aspx`,
			headers: {
				Referer: `${this.config.zf.url}xs_main.aspx?xh=${userId}`
			},
			cookie,
			data: {
				xh: userId,
				gnmkdm:'N121203'
			},
			getStatus: true
		})
		const {status, data} = result
		if(status.code != 200) {
			await this._zfLogout(user)
			return this.reject('-3003', 'zf resources not found')
		}
		const grabCourseList = await this._convertGrabCourse(data)
		console.log('get zf grab course data', grabCourseList)
		return grabCourseList
	}

	async getSportsGrabCourse(user) {
		if(!this._checkZfLogin(user))
			return this.reject('-3007', 'zf user not logined in')
		const {userId, session} = user.data.zf
		let cookie = {}
	 	cookie[this.config.zf.url] = {
			'ASP.NET_SessionId': session
		}
		const result = await this.common.reqGet({
			url: `${this.config.zf.url}xstyk.aspx`,
			headers: {
				Referer: `${this.config.zf.url}/xs_main.aspx?xh=${userId}`
			},
			cookie,
			data: {
				xh: userId
			},
			getStatus: true
		})
		const {status, data} = result
		if(status.code != 200) {
			await this._zfLogout(user)
			return this.reject('-3003', 'zf resources not found')
		}
		if(/alert\('您现在不能选该类课程!'\)/.test(data)) {
			console.error('sports grab course unopend')
			return []
		}
		const sportsGrabCourseList = await this._getSportsGrabCourseInfo(data, user)
		console.log('get zf sports grab course data', sportsGrabCourseList)
		return sportsGrabCourseList
	}

	async sendGrabCourse(user, courseTids, targetData) {
		if(!this._checkZfLogin(user))
			return this.reject('-3007', 'zf user not logined in')
		const viewState = await this._getGrabViewState(user)
		const {userId, session} = user.data.zf
		let cookie = {}
	 	cookie[this.config.zf.url] = {
			'ASP.NET_SessionId': session
		}
		let reqData = {
			__EVENTTARGET: '',
			__EVENTARGUMENT: '',
			__VIEWSTATE: viewState,
			ddl_kcxz: '',
			ddl_ywyl: '有',
			ddl_kcgs: '',
			ddl_sksj: '',
			ddl_xqbs: 1,
			TextBox1: ''
		}
		Object.assign(reqData, targetData)
		const result = await this.common.reqPost({
			url: `${this.config.zf.url}xf_xsqxxxk.aspx`,
			headers: {
				Referer: `${this.config.zf.url}xs_main.aspx?xh=${userId}`
			},
			cookie,
			getData: {
				xh: userId,
				gnmkdm: 'N121203'
			},
			data: reqData,
			getStatus: true
		})
		const {status, data} = result
		if(status.code != 200) {
			await this._zfLogout(user)
			return this.reject('-3003', 'zf resources not found')
		}
		const $ = this.common.parseHTML(data)
		const list = $('#DataGrid2 tbody tr')
		if(list.length > 1) {
			let finishTids = []
			list.each(function(index) {
				if(index == 0)
					return
				finishTids = courseTids.filter((tid) => {
					return $(this).text().indexOf(tid)
				})
			})
			console.log(finishTids)
			if(finishTids.length == 0)
				return []
			return finishTids
		}
		else
			return []
	}

	async getStuZfPhoto(user) {
		const {userId, session} = user.data.zf
		let cookie = {}
	 	cookie[this.config.zf.url] = {
			'ASP.NET_SessionId': session
		}
		const result = await this.common.reqGet({
			url: `${this.config.zf.url}xsjxpj.aspx`,
			headers: {
				Referer: `${this.config.zf.url}xs_main.aspx?xh=${userId}`
			},
			cookie,
			data: {
				xkkh: evaluationId,
				xh: userId,
				gnmkdm: 'N12141'
			},
			getStatus: true
		})
		const {status, data} = result
		if(status.code != 200) {
			await this._zfLogout(user)
			return this.reject('-3003', 'zf resources not found')
		}
		const $ = await this.common.parseHTML(data)
	}

	/*
	
	 [public] 自动识别正方验证码
	
	 @return [object] 数据类型 数据长度 数据
	
	*/

	async _zfCaptchaRecognition() {
		let cookie
		const result = await this.common.reqGet({
			url: `${this.config.zf.url}CheckCode.aspx`,
			getCookie: true,
			getContentInfo: true,
			getBuffer: true,
			getStatus: true
		})
		const {status, contentType, contentLen, data} = result
		if(status.code == 302) 
			return this.reject('-3003', 'zf resources not found')
		const recResult = await this.common.reqPost({
			url: `${this.config.zf.captchaRecognitionUrl}`,
			headers: {
				'content-type': 'application/x-www-form-urlencoded',
				charset: 'UTF-8'
			},
			data: {
				data: data.toString('base64')
			},
			getStatus: true
		})
		const {status: recStatus, data: recData} = recResult
		if(!result.cookie[0] || recStatus.code != 200 || !recData || !recData.data || !/^[a-zA-Z0-9]{4}$/.test(recData.data)) 
			return this.reject('-1072', 'captcha recognition service error')
		const captcha = recData.data
		let zfSession = result.cookie[0]['ASP.NET_SessionId']
		console.log(`zf session is ${zfSession}`)
		return {
			captcha,
			zfSession
		}
	}

	/**
	 *
	 * [public] 登出系统
	 *
	 * @param [object] user
	 *
	 * @return [number] 1
	 *
	 */

	async _zfLogout(user) {
	 	user.data.zf = {
	 		userId: undefined,
 			logined: false,
 			session: undefined,
 			time: 0
 		}
	 	await this.common.updateSessionData(user.session, {
	 		zf: user.data.zf
	 	})
	}

	/**
	 *
	 * [public] 登出CAS中央授权系统
	 *
	 * @param [object] user
	 *
	 * @return [number] 1
	 *
	 */

	async _casLogout(user) {
		user.data.cas = {
			userId: undefined,
			logined: false,
			tgc: undefined,
			session: undefined,
			time: 0
		}
		if(!user.session)
			return
		await this.common.updateSessionData(user.session, {
			cas: user.data.cas
	 	})
	}

	async _getGrabViewState(user) {
		if(!this._checkZfLogin(user))
			return this.reject('-3007', 'zf user not logined in')
		const {userId, session} = user.data.zf
		console.log(user)
		let ctask = await this.redis.grab.get(`ctask@${user.userId}`, true)
		if(ctask && ctask.viewState)
			return ctask.viewState
		let cookie = {}
	 	cookie[this.config.zf.url] = {
			'ASP.NET_SessionId': session
		}
		const result = await this.common.reqGet({
			url: `${this.config.zf.url}xf_xsqxxxk.aspx`,
			headers: {
				Referer: `${this.config.zf.url}xs_main.aspx?xh=${userId}`
			},
			cookie,
			data: {
				xh: userId,
				gnmkdm: 'N121203'
			},
			getStatus: true
		})
		const {status, data} = result
		if(status.code != 200) {
			await this._zfLogout(user)
			return this.reject('-3003', 'zf resources not found')
		}
		const $ = this.common.parseHTML(data, false)
		const viewState = $('input[name="__VIEWSTATE"]').val().trim()
		if(viewState.length == 0)
			return this.reject('-3037', 'get grab viewstate failed')
		ctask.viewState = viewState
		await this.redis.grab.set(`ctask@${user.userId}`, ctask)
		return viewState
	}

	_getSportsGrabCourseInfo(htmlStr, user) {
		return new Promise(async (resolve, reject) => {
			try {
				const that = this
				const {userId, session} = user.data.zf
				const $ = this.common.parseHTML(htmlStr, false)
				const viewState = $('input[name="__VIEWSTATE"]').val()
				let sportsGrabCourseList = []
				let cookie = {}
			 	cookie[this.config.zf.url] = {
					'ASP.NET_SessionId': session
				}
				const options = $('#ListBox1').children('option')
				if(options.length == 0)
					resolve([])
				options.each(async function(index) {
					const temp =  $(this).text().split('‖')
					if(!temp || !temp[0] || !temp[1])
						reject({code: '-3027', msg: 'zf sports grab course name invalid'})
					const courseTid = temp[0]
					const _courseName = temp[1]
					console.log(`sync grab course ${_courseName}`)
					const result = await that.common.reqPost({
						url: `${that.config.zf.url}xstyk.aspx`,
						cookie,
						headers: {
							'content-type': 'application/x-www-form-urlencoded',
							Referer: `${that.config.zf.url}xstyk.aspx?xh=${userId}`,
							charset: 'UTF-8'
						},
						getData: {
							xh: userId
						},
						data: {
							__EVENTTARGET: 'ListBox1',
							__EVENTARGUMENT: '',
							__VIEWSTATE: viewState,
							DropDownList1: '项目',
							ListBox1: courseTid
						},
						getStatus: true
					})
					const {status, data} = result//1701170510 301316
					if(status.code != 200) {
						await that._zfLogout(user)
						reject({code: '-3003', msg: 'zf resources not found'})
					}
					const $$ = that.common.parseHTML(data, false)
					const _viewState = $$('input[name="__VIEWSTATE"]').text()
					const options2 = $$('#ListBox2').children('option')
					console.log('课程', index, options.length - 1)
					if(options2.length == 0) {
						if(index == options.length - 1)
							resolve(sportsGrabCourseList)
						return
					}
					options2.each(function(_index) {
						//4(2017-2018-2)-PC060001-1701170120#(2017-2018-2)-PC060001-1022-8
						const courseGid = $$(this).val()
						//篮球‖2.0‖卢嘉颖‖‖周三第7,8节{第2-17周}‖篮球场‖51‖50‖,17软件1班,17软件2班,17工管5班,17工管6班,17会计7班,17理财1班,17一体化1班,‖本部
						const [courseName, courseCredit, courseTch, courseTchTitle, courseTime, courseRoom, courseVal, courseCount] = $$(this).text().split('‖')
						const courseTimeList = that.hd.syllabus.convertStuCourseTime(courseTime)
						sportsGrabCourseList.push({
							courseTid,
							courseName,
							courseTimeList,
							courseTch: [courseTch],
							courseRoom,
							courseCount,
							courseData: {
								//courseGid
								cg: courseGid
							}
						})
						console.log('子课程', _index, options2.length - 1, sportsGrabCourseList)
						if(_index == options2.length - 1 && index == options.length - 1)
							resolve(sportsGrabCourseList)
					})
				})
			}
			catch(err) {
				reject({code: '-3028', msg: 'handle zf sports grab course failed'})
			}
		})
	}

	 /**
	  *
	  * [private] 获取学生信息
	  *
	  * @param [object] user
	  *
	  */

	async _getStuInfo(user) {
		if(!this._checkZfLogin(user))
			return this.reject('-3007', 'zf user not logined in')
		const {userId, session, verifyCode} = user.data.zf
		let cookie = {}
	 	cookie[this.config.zf.url] = {
			'ASP.NET_SessionId': session
		}
		const result = await this.common.reqGet({
			url: `${this.config.zf.url}xsgrxx.aspx`,
			cookie,
			headers: {
				Referer: `${this.config.zf.url}xs_main.aspx?xh=${userId}`
			},
	 		data: {
	 			xh: userId,
	 			xm: 'test',
	 			gnmkdm: 'N121501'
	 		},
	 		json: false,
	 		getStatus: true
		})
		const {status, data} = result
		if(status.code != 200) {
			await this._zfLogout(user)
			return this.reject('-3003', 'zf resources not found')
		}
		if(/你还没有进行本学期的教学质量评价/.test(data)) {
			await this._zfLogout(user)
			return this.reject('-3071', '您还未进行评教，无法绑定，请先到教务系统评教')
		}
		let stuData = await this._convertStuData(data)
		stuData.stuZfAuthId = verifyCode || '-1'
		console.log('get zf student info', stuData)
		return stuData
	}

	async _getTchInfo(user) {
		if(!this._checkZfLogin(user))
			return this.reject('-3007', 'zf user not logined in')
		const {userId, session, verifyCode} = user.data.zf
		let cookie = {}
	 	cookie[this.config.zf.url] = {
			'ASP.NET_SessionId': session
		}
		const result = await this.common.reqGet({
			url: `${this.config.zf.url}js_grjl.aspx`,
			cookie,
			headers: {
				Referer: `${this.config.zf.url}js_main.aspx?xh=${userId}&zgh=${userId}`
			},
	 		data: {
	 			zgh: userId,
	 			xm: 'test',
	 			gnmkdm: 'N122201'
	 		},
	 		json: false,
	 		getStatus: true
		})
		const {status, data} = result
		console.log(data)
		if(status.code != 200) {
			await this._zfLogout(user)
			return this.reject('-3003', 'zf resources not found')
		}
		let tchData = await this._convertTchData(data)
		tchData.tchZfAuthId = verifyCode || '-1'
		console.log('get zf teacher info', tchData)
		return tchData
	}

	async _convertStuData(htmlStr) {
		const $ = await this.common.parseHTML(htmlStr)
		const birth = $('#lbl_csrq').text().trim()
		const enrollment = $('#lbl_rxrq').text().trim()
		return {
			//学号
			stuId: $('#xh').text().trim() || '-1',
			//名字
			stuName: $('#xm').text().trim() || '-1',
			//性别
			stuSex: (['男', '女'].indexOf($('#lbl_xb').text().trim())) + 1,
			//照片链接
			stuPhoto: $('#xszp').attr('src').trim() || '-1',
			//院系
			stuFaculty: $('#lbl_xy').text().trim() || '-1',
			//专业
			stuMajor: $('#lbl_zymc').text().trim() || '-1',
			//年级
			stuGrade: $('#lbl_dqszj').text().trim() || '-1',
			//班级
			stuClass: $('#lbl_xzb').text().trim() || '-1',
			//出生日期
			stuBirth: (birth == '' ? '-1' : this.common.dateStr2timestamp(birth)),
			//入学日期
			stuEnrollment: (enrollment == '' ? '-1' : this.common.dateStr2timestamp(enrollment)),
			//学生证号
			stuCardId: $('#lbl_xszh').text().trim() || '-1',
			//手机号码
			stuPhone: $('#lbl_TELNUMBER').text().trim() || '-1',
			//身份证号
			stuIdCard: $('#lbl_sfzh').text().trim() || '-1',
			//考生号
			stuExamId: $('#lbl_ksh').text().trim() || '-1',
			//学历层次
			stuEdu: $('#lbl_CC').text().trim() || '-1',
			//民族
			stuNation: $('#lbl_mz').text().trim() || '-1',
			//政治面貌
			stuPolicital: $('#lbl_zzmm').text().trim() || '-1',
			//学籍状态
			stuRollStatus: (['有', '无'].indexOf($('#lbl_xjzt').text().trim())) + 1,
			//学制
			stuStudyLen: $('#lbl_xz').text().trim() || '-1',
			//学习年限
			stuStudyYearLen: $('#lbl_xxnx').text().trim() || '-1'
		}
	}

	async _convertTchData(htmlStr) {
		const $ = await this.common.parseHTML(htmlStr)
		const sex = $('#xb').children('option[selected="selected"]')
		const nation = $('#mz').children('option[selected="selected"]')
		const birth = new Date(($('#csrq').val() || '').trim()).getTime()
		const policital = $('#zzmm').children('option[selected="selected"]')
		const faculty = $('#bm').children('option[selected="selected"]')
		const staffRoom = $('#ks').children('option[selected="selected"]')
		const edu = $('#xl').children('option[selected="selected"]')
		const degree = $('#xw').children('option[selected="selected"]')
		const title = $('#zc').children('option[selected="selected"]')
		const isExperimenter = $('#SFSYSRY').children('option[selected="selected"]')
		return {
			//工号
			tchId: $('#zgh1').text().trim() || '-1',
			//名字
			tchName: $('#xm').text().trim() || '-1',
			//性别
			tchSex: sex.length > 0 ? (['男', '女'].indexOf(sex.eq(0).text().trim())) + 1 : '-1',
			//照片链接
			tchPhoto: $('#Image1').attr('src').trim() || '-1',
			//民族
			tchNation: nation.length > 0 ? ((nation.eq(0).text().indexOf('请选择') == -1 ? nation.eq(0).text().trim()  : '-1') || '-1') : '-1',
			//出生日期
			tchBirth: birth ? NaN : '-1',
			//政治面貌
			tchPolicital: policital.length > 0 ? ((policital.eq(0).text().indexOf('请选择') == -1 ? policital.eq(0).text().trim()  : '-1') || '-1') : '-1',
			//院系
			tchFaculty: faculty.length > 0 ? (faculty.eq(0).text().trim() || '-1') : '-1',
			//教研室
			tchStaffRoom: staffRoom.length > 0 ? (staffRoom.eq(0).text().trim() || '-1') : '-1',
			//手机号码
			tchPhone: ($('#lxdh').val() || '').trim() || '-1',
			//电子邮箱
			tchEmail: ($('#emldz').val() || '').trim() || '-1',
			//毕业院校
			tchUniversity: ($('#byyx').val() || '').trim() || '-1',
			//毕业专业
			tchMajor: ($('#zymc').val() || '').trim() || '-1',
			//学历层次
			tchEdu: edu.length > 0 ? (edu.eq(0).text().trim() || '-1') : '-1',
			//学位
			tchDegree: degree.length > 0 ? ((degree.eq(0).text().indexOf('请选择') == -1 ? degree.eq(0).text().trim()  : '-1') || '-1') : '-1',
			//职称
			tchTitle: title.length > 0 ? (title.eq(0).text().trim() || '-1') : '-1',
			//职务
			tchJob: ($('#zw').val() || '').trim() || '-1',
			//学科方向
			tchSubject: ($('#jxyjfx').val() || '').trim() || '-1',
			//教师资格证号
			tchCertNum: ($('#jszgzh').val() || '').trim() || '-1',
			//主讲教师资格认证号
			tchLectureNum: ($('#zjjszgrzh').val() || '').trim() || '-1',
			//人事职工号
			tchHumanId: ($('#rszgh').val() || '').trim() || '-1',
			//是否实验室人员
			tchIsExperimenter: isExperimenter.length > 0 ? (['否', '是'].indexOf(isExperimenter.eq(0).text().trim())) : 0,
			//教学质量评价
			tchEvaluation: ($('#jxzlpj').val() || '').trim() || '-1',
			//教师简介
			tchSummary: ($('#jsjj').val() || '').trim() || '-1'
		}
	}

	_convertGrabCourse(htmlStr) {
		const that = this
		const $ = this.common.parseHTML(htmlStr, false)
		let grabCourseList = []
		$('#kcmcGrid tbody tr').each(function() {
			if($(this).attr('class') == 'datelisthead')
				return
			const item = $(this).children('td')
			const courseTime = item.eq(5).text()
			const courseTimeList = that.hd.syllabus.convertStuCourseTime(courseTime)
			const courseTch = item.eq(4).text()
			const courseTchList = that.hd.syllabus.convertCourseTch(courseTch)
			grabCourseList.push({
				courseName: item.eq(2).text(),
				courseTid: that.common.trim(item.eq(3).text()),
				courseTch: courseTchList,
				courseTimeList,
				courseRoom: that.common.trim(item.eq(6).text()).split(';'),
				courseCount: parseInt(that.common.trim(item.eq(10).text())),
				courseData: {
					//confirmBox
					cb: item.eq(0).children('input').attr('id'),
					//bookBox
					bb: item.eq(1).children('input').attr('id')
				}
			})
		})
		return grabCourseList
	}

	
	/*
		一个待修复bug
		生产与运作管理实务 周二第1,2节{第1-16周} 胡国辉 教2-611 1 2
3|server4  | 生产与运作管理实训 周四第1,2,3,4节{第17-17周} 田巧/梅娟/胡丽艳/梅娟 教3-103 3 2
3|server4  |   --> post /user/bind/student 500 13s 69b
3|server4  | { code: '-3014', msg: 'cannot convert course time' }
3|server4  | post /user/bind/student  request failed: [-3014]cannot convert course time
3|server4  | interface return error: -3014 cannot convert course time

	*/

	

	async _setCasSession(user) {
	 	let cookie
		if(user.data && user.data.cas && user.data.cas.session && user.data.cas.logined) {
			cookie = {}
			cookie[this.config.cas.url] = {
				'JSESSIONID': user.data.cas.session
			}
		}
		const result = await this.common.reqGet({
			cookie,
			url: `${this.config.cas.url}login`,
			data: {
				service: 'http://120.86.68.211:8080/Login'
			},
			ignoreAuth: true,
			getCookie: true
		})
		console.log(result.cookie)
		const casSession = result.cookie[0] ? result.cookie[0]['JSESSIONID'] : user.data.cas.session
		console.log(`cas session is ${casSession}`)
		const $ = await this.common.parseHTML(result.data)
		const userLT = $('input[name=lt]').val()
		const userExec = $('input[name=execution]').val()
		if(!userLT || !userExec) {
			await this._casLogout(user)
			return this.reject('-3017', 'cas login lt or execution not found')
		}
		if(!user.data)
			user.data = {}
		user.data.cas = {
			session: casSession
		}
		return {
			userLT,
			userExec
		} 
	}

	 /**
	  *
	  * [private] 检查系统session是否登录
	  *
	  * @param [object] user
	  *
	  * @return [number] 1
	  *
	  */

	// _checkZfSession(user, userId) {
	// 	console.log(user.data.zf)
	// 	if(!user.data.zf || !user.data.zf.logined || !user.data.zf.session || !user.data.zf.time || (parseInt(Date.now() / 1000) - user.data.zf.time) > this.config.zf.sessionExpires || (userId && userId != user.data.zf.userId))
	// 		return false
	// 	return true
	// }

	// _checkCasSession(user, userId) {
	// 	console.log(user.data.cas)
	// 	if(!user.data.cas || !user.data.cas.logined || !user.data.cas.session || !user.data.cas.time || (parseInt(Date.now() / 1000) - user.data.cas.time) > this.config.cas.sessionExpires || (userId && userId != user.data.cas.userId))
	// 		return false
	// 	return true
	// }

	_checkZfLogin(user, userId) {
		console.log(user)
		if(!user || !user.data || !user.data.zf || !user.data.zf.logined || !user.data.zf.session || !user.data.zf.time || (parseInt(Date.now() / 1000) - user.data.zf.time) > this.config.frame.sessionExpires.zf || (userId && userId != user.data.zf.userId)) {
			console.error('zf user not login')
			return false
		}
		console.log('zf user logined')
		return true
	}

	_checkCasLogin(user, userId, userHashPwd) {
		console.log(user)
		if(!user || !user.data || !user.data.cas || !user.data.cas.logined || !user.data.cas.session || !user.data.cas.time || (parseInt(Date.now() / 1000) - user.data.cas.time) > this.config.frame.sessionExpires.cas || (userId && userId != user.data.cas.userId) || (userHashPwd && user.data.cas.userHashPwd && userHashPwd != user.data.cas.userHashPwd)) {
			console.error('cas user not login')
			return false
		}
		console.log('cas user logined')
		return true
	}

	_checkZfAuthId(zfAuthId) {
		return /^[A-Z0-9]{32}$/.test(zfAuthId)
	}

}

module.exports = h_zf

// async _getStuScoreViewState(user) {
	// 	if(!this.checkCasLogin(user))
	// 		return this.reject('-3007', 'zf user not logined in')
	// 	const {userId, session} = user.data.zf
	// 	let cookie = {}
	// 	cookie[this.config.zf.url] = {
	// 		'ASP.NET_SessionId': session
	// 	}
	// 	const result = await this.common.reqGet({
	// 		url: `${this.config.zf.url}xscj_gc.aspx`,
	// 		cookie,
	// 		headers: {
	// 			Referer:  `${this.config.zf.url}xs_main.aspx?xh=${userId}`
	// 		},
	// 		data: {
	// 			xh: userId,
	// 			gnmkdm: 'N121605'
	// 		},
	// 		getStatus: true
	// 	})
	// 	const {status, data} = result
	// 	if(status.code != 200) {
	// 		await this._zfLogout(user)
	// 		return this.reject('-3003', 'zf resources not found')
	// 	}
	// 	const $ = this.common.parseHTML(data)
	// 	const viewState = $('input[name="__VIEWSTATE"]').val().trim()
	// 	if(viewState.length == 0)
	// 		return this.reject('-3036', 'get score viewstate failed')
	// 	return viewState
	// }